﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#ifndef __AUTHOR_SESSION_H__
#define __AUTHOR_SESSION_H__

#pragma once

#include "refcount.h"
#include "sessionbase.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 授权会话数据
struct tagAUTHOR_SESSION : public SESSION_ID
{
public:
    UInt     uStatus;   // atomics
    UInt     uTimeId;   // 检测标志
    UInt     uTryCount; // 尝试次数
    UInt     uSelect;   // (现在不支持手动选择)FALSE---自动选择业务管理, TRUE---手动选择业务管理, 强制升级忽略本选项直接自动连升级业务管理
    PINDEX   index;
};
typedef tagAUTHOR_SESSION AUTHOR_SESSION, *PAUTHOR_SESSION;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 授权会话
class CAuthorSession : public CTRefCount<CAuthorSession>
{
public:
    CAuthorSession(void)
    {
    }

    virtual ~CAuthorSession(void)
    {
    }
public:
    void Reset(void)
    {
        MM_SAFE::Set(&m_Session, 0, sizeof(AUTHOR_SESSION));
    }

    LLong GetUpdate(void)
    {
        return m_Session.llUpdate;
    }

    void SetUpdate(LLong llUpdate)
    {
        CAtomics::Exchange64<LLong>(&m_Session.llUpdate, llUpdate);
    }

    bool TrySetUpdate(LLong llCurUpdate, LLong llSetUpdate)
    {
        return (CAtomics::CompareExchange64<LLong>(&m_Session.llUpdate, llSetUpdate, llCurUpdate) == llCurUpdate);
    }

    bool CheckUpdate(LLong llUpdate)
    {
        return (CAtomics::CompareExchange64<LLong>(&m_Session.llUpdate, 0, 0) == llUpdate);
    }

    bool TimeoutUpdate(LLong llInterval)
    {
        return (CPlatform::GetRunningTime() > (m_Session.llUpdate + llInterval));
    }

    UInt GetVer(void)
    {
        return m_Session.uVer;
    }

    void SetVer(UInt uVer)
    {
        m_Session.uVer = uVer;
    }

    UInt GetTarget(void)
    {
        return m_Session.uTarget;
    }

    void SetTarget(UInt uTarget)
    {
        m_Session.uTarget = uTarget;
    }

    UInt GetType(void)
    {
        return m_Session.uType;
    }

    void SetType(UInt uType)
    {
        m_Session.uType = uType;
    }

    UInt GetId(void)
    {
        return m_Session.uId;
    }

    void SetId(UInt uId)
    {
        m_Session.uId = uId;
    }

    ULLong GetllId(void)
    {
        return m_Session.ullId;
    }

    void SetllId(ULLong ullId)
    {
        m_Session.ullId = ullId;
    }
    //--------------------------------------------
    UInt GetStatus(void)
    {
        return CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0);
    }

    bool CheckStatus(UInt uStatus)
    {
        return (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0) == uStatus);
    }

    bool CheckStatusLTOE(UInt uStatus)
    {
        return (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0) <= uStatus);
    }

    bool CheckStatusGTOE(UInt uStatus)
    {
        return (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0) >= uStatus);
    }

    void SetStatus(UInt uStatus)
    {
        CAtomics::Exchange<UInt>(&m_Session.uStatus, uStatus);
    }

    bool TrySetStatus(UInt uCurStatus, UInt uSetStatus)
    {
        return (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, uSetStatus, uCurStatus) == uCurStatus);
    }

    bool TrySetStatusLTOE(UInt uCurStatus, UInt uSetStatus)
    {
        if (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0) <= uCurStatus)
        {
            CAtomics::Exchange<UInt>(&m_Session.uStatus, uSetStatus);
            return true;
        }
        return false;
    }

    bool TrySetStatusGTOE(UInt uCurStatus, UInt uSetStatus)
    {
        if (CAtomics::CompareExchange<UInt>(&m_Session.uStatus, 0, 0) >= uCurStatus)
        {
            CAtomics::Exchange<UInt>(&m_Session.uStatus, uSetStatus);
            return true;
        }
        return false;
    }

    UInt GetTimeId(void)
    {
        return CAtomics::CompareExchange<UInt>(&m_Session.uTimeId, 0, 0);
    }

    void SetTimeId(UInt uTimeId)
    {
        CAtomics::Exchange<UInt>(&m_Session.uTimeId, uTimeId);
    }

    bool TrySetTimeId(UInt uCurTimeId, UInt uSetTimeId)
    {
        return (CAtomics::CompareExchange<UInt>(&m_Session.uTimeId, uSetTimeId, uCurTimeId) == uCurTimeId);
    }

    UInt GetTryCount(void)
    {
        return m_Session.uTryCount;
    }

    void SetTryCount(UInt uTryCount = 0)
    {
        m_Session.uTryCount = uTryCount;
    }

    UInt IncrTryCount(void)
    {
        ++m_Session.uTryCount;
        return m_Session.uTryCount;
    }

    bool OutTryCount(UInt uMaxCount)
    {
        ++m_Session.uTryCount;
        return (m_Session.uTryCount > uMaxCount);
    }

    UInt GetSelect(void)
    {
        return m_Session.uSelect;
    }

    void SetSelect(UInt uSelect = FALSE)
    {
        m_Session.uSelect = uSelect;
    }

    PINDEX GetIndex(void)
    {
        return (PINDEX)CAtomics::CompareExchangePtr((void* volatile*)&m_Session.index, nullptr, nullptr);
    }

    void SetIndex(PINDEX index)
    {
        CAtomics::ExchangePtr((void* volatile*)&m_Session.index, index);
    }

    PByte GetSession(void)
    {
        return (PByte)&m_Session;
    }
public:
    AUTHOR_SESSION   m_Session;
};
typedef CTRefCountPtr<CAuthorSession>   CAuthorSessionPtr;

typedef CTMap<Socket_t, CAuthorSessionPtr>         AUTHOR_SESSION_MAP, *PAUTHOR_SESSION_MAP;
typedef CTMap<Socket_t, CAuthorSessionPtr>::PAIR   AUTHOR_SESSION_MAP_PAIR;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
typedef CTMap<Socket_t, PINDEX>                    AUTHOR_INDEX_MAP, *PAUTHOR_INDEX_MAP;
typedef CTMap<Socket_t, PINDEX>::PAIR              AUTHOR_INDEX_MAP_PAIR;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 签证排队数据
struct tagAUTHOR_VISA : public MObject
{
    ULLong   ullAuthor;
    ULLong   ullMaster;
};
typedef tagAUTHOR_VISA AUTHOR_VISA, *PAUTHOR_VISA;
typedef CTQueue<AUTHOR_VISA>         AUTHOR_VISA_QUEUE;

#endif // __AUTHOR_SESSION_H__
